﻿#pragma once
//#include <stdio.h>
//#include <windows.h>

#include "common.h"
//#include <atomic>


// 忽略 MSVC 警告错误 4996
#if defined(_MSC_VER)
    #pragma warning(default:4996)
#endif

// ffmpeg
extern "C" {
    #include <libavformat/avformat.h>
    #include <libavcodec/avcodec.h>
    #include <libavutil/opt.h>
    #include <libavutil/channel_layout.h>
    #include <libswresample/swresample.h>
    #include <libavutil/avutil.h>
    #include <libavutil/samplefmt.h>
}

// C++
//#include <iostream>
//#include <string>
//#include <stdexcept>
//#include <thread>
//#include <stdexcept>

// Qt
//#include <QDebug>
//#include <QDir>
//#include <QFile>


// struct pcm_format
static struct PcmFormat {
    PcmFormat() {}
        //: in_sample_rate(44100)
        //, in_sample_fmt(AV_SAMPLE_FMT_S16)
        //, out_sample_rate(44100)
        //, out_sample_fmt(AV_SAMPLE_FMT_S16)
        //, is_pcm_input(false)
    //{ in_layout = AV_CHANNEL_LAYOUT_STEREO;
    //  out_layout = AV_CHANNEL_LAYOUT_STEREO; }

    void set_in_format(int layout, int sample_rate, AVSampleFormat sample_fmt) {
        av_channel_layout_default(&in_layout, layout);
        in_sample_rate = sample_rate;
        in_sample_fmt = sample_fmt;
    }

    void set_out_format(int layout, int sample_rate, AVSampleFormat sample_fmt) {
        av_channel_layout_default(&out_layout, layout);
        out_sample_rate = sample_rate;
        out_sample_fmt = sample_fmt;
    }

    AVChannelLayout in_layout = AV_CHANNEL_LAYOUT_STEREO;
    int             in_sample_rate = 44100;
    AVSampleFormat  in_sample_fmt = AV_SAMPLE_FMT_S16;

    AVChannelLayout out_layout = AV_CHANNEL_LAYOUT_STEREO;
    int             out_sample_rate = 44100;
    AVSampleFormat  out_sample_fmt = AV_SAMPLE_FMT_S16;

    bool is_pcm_input = false;
};
extern PcmFormat transcode_pcm;


class AudioTranscoder : public QObject
{
    Q_OBJECT

public:
    AudioTranscoder(const std::string& input_filename, const std::string& output_filename);
    ~AudioTranscoder();
    void transcode();
    void start();

    std::atomic<bool> is_transcoding;


signals:
    void transcodeFinished(int64_t time_now);


private:
    AVFormatContext* input_format_context;
    AVFormatContext* output_format_context;
    AVCodecContext*  input_codec_context;
    AVCodecContext*  output_codec_context;
    AVStream*        input_stream;
    AVStream*        output_stream;
    SwrContext*      resample_context;
    AVFrame*         input_frame;
    AVFrame*         output_frame;
    AVPacket*        packet;
    std::string input_filename;
    std::string output_filename;
    //std::mutex  mutex;
    int  encoder_frame_size; // 编码帧打包大小
    bool is_pcm_output;    // 判断 pcm 输出格式

    void open_input_file(bool is_pcm_input = false);
    void open_output_file(const char* output_suffix = ".mp3");
    void init_resample_context();
    void transcode_audio();
    void transcode_audio_pcm();
};
